
using System;
using Gtk;
using System.Windows.Media;
using MonoDevelop.XamlDesigner.Controller;
using System.Windows;

namespace MonoDevelop.XamlDesigner
{
	internal class WidgetTreeCombo: Button
	{
		Label label;
		Image image;
		System.Windows.FrameworkElement rootWidget;
		System.Windows.FrameworkElement selection;
		WidgetTreePopup popup;
        MoonlightController controller;
		
		public WidgetTreeCombo (MoonlightController controller)
		{
            this.controller = controller;
            
            
			label = new Label ();
			image = new Gtk.Image ();
			
			HBox bb = new HBox ();
			bb.PackStart (image, false, false, 3);
			bb.PackStart (label, true, true, 3);
			label.Xalign = 0;
			label.HeightRequest = 18;
			bb.PackStart (new VSeparator (), false, false, 1);
			bb.PackStart (new Arrow (ArrowType.Down, ShadowType.None), false, false, 1);
			Child = bb;
			this.WidthRequest = 300;
			Sensitive = true;
            rootWidget = controller.Root;
            Selection =  controller.Root;
            
		}
		
		public override void Dispose ()
		{
			if (popup != null)
				popup.Destroy ();
			base.Dispose ();
		}

		
		public System.Windows.FrameworkElement RootWidget {
			get { return rootWidget; }
			set {
				rootWidget = value;
				Sensitive = rootWidget != null;
				Update ();
			}
		}
		
		public System.Windows.FrameworkElement Selection 
		{
            set {
				selection = value;
				Update ();
            }
            get {
                return selection;
            }
		}
		
		void Update ()
		{
			if (selection != null) {
                if (!string.IsNullOrEmpty(selection.Name))
					label.Text = selection.Name;
                else
                    label.Text = selection.GetType().Name;
				image.Pixbuf = null;//TODO icon
				image.Show ();
			} else {
				label.Text = "             ";
				image.Hide ();
			}
            GLib.Timeout.Add (10, delegate {
                controller.ChangeSelection (Selection);
				return false;
			});
		}
		
		protected override void OnPressed ()
		{
			base.OnPressed ();
			if (popup == null) {
				popup = new WidgetTreePopup (rootWidget);
				popup.WidgetActivated += OnPopupActivated;
				popup.SetDefaultSize (Allocation.Width, 500);
			}
			else if (popup.Visible) {
				popup.Hide ();
				return;
			}
			
			int x, y;
			ParentWindow.GetOrigin (out x, out y);
			x += Allocation.X;
			y += Allocation.Y + Allocation.Height;
			
			popup.Fill (RootWidget);
			popup.Move (x, y);
			popup.ShowAll ();
		}
		
		protected override bool OnFocusOutEvent (Gdk.EventFocus evnt)
		{
			if (popup != null)
				popup.Hide ();
			return base.OnFocusOutEvent (evnt);
		}

		
		void OnPopupActivated (object s, EventArgs a)
		{
			popup.Hide ();
			Selection = popup.Selection;
		}
	}
	
	class WidgetTreePopup: Window
	{
		TreeView tree;
		TreeStore store;
		System.Windows.FrameworkElement selection;
		System.Windows.FrameworkElement rootWidget;
		
		public event EventHandler WidgetActivated;
		
		public WidgetTreePopup (System.Windows.FrameworkElement rootWidget): base (WindowType.Popup)
		{
			this.rootWidget = rootWidget;
			Gtk.Frame frame = new Frame ();
			frame.ShadowType = Gtk.ShadowType.Out;
			Add (frame);
			
			Gtk.ScrolledWindow sc = new ScrolledWindow ();
			sc.VscrollbarPolicy = PolicyType.Automatic;
			sc.HscrollbarPolicy = PolicyType.Automatic;
			frame.Add (sc);
			
			tree = new TreeView ();
			store = new TreeStore (typeof(Gdk.Pixbuf), typeof(string), typeof(System.Windows.FrameworkElement));
			tree.Model = store;
			tree.HeadersVisible = false;
			
			TreeViewColumn col = new TreeViewColumn ();
			CellRendererPixbuf cr = new CellRendererPixbuf ();
			col.PackStart (cr, false);
			col.AddAttribute (cr, "pixbuf", 0);
			
			CellRendererText tr = new CellRendererText ();
			col.PackStart (tr, true);
			col.AddAttribute (tr, "markup", 1);
			
			tree.AppendColumn (col);
			
			tree.ButtonReleaseEvent += OnButtonRelease;
			tree.RowActivated += OnButtonRelease;
			sc.Add (tree);
			tree.GrabFocus ();
			
		}
		
		public void Fill (System.Windows.FrameworkElement widget)
		{
			store.Clear ();
			Fill (TreeIter.Zero, widget);
		}
		
		public void Fill (TreeIter iter, System.Windows.FrameworkElement widget)
		{
            string txt = ((System.Windows.FrameworkElement)widget).Name;
            //TODO good icon
            
            if (string.IsNullOrEmpty(txt))
                txt = widget.GetType().Name;
            txt = "<b>" + txt + "</b>";
            
			if (!iter.Equals (TreeIter.Zero))
				iter = store.AppendValues (iter, Gdk.Pixbuf.LoadFromResource("MonoDevelop.XamlDesigner.Icons.circle-tool.png"), txt, widget);
			else
				iter = store.AppendValues ( Gdk.Pixbuf.LoadFromResource("MonoDevelop.XamlDesigner.Icons.circle-tool.png"), txt, widget);
            
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(widget); i++)
			{
				DependencyObject child = VisualTreeHelper.GetChild(widget, i);
                if (child is FrameworkElement)
					Fill(iter, (FrameworkElement)child);
			}
            
			if (widget == selection) {
				tree.ExpandToPath (store.GetPath (iter));
				tree.ExpandRow (store.GetPath (iter), false);
				tree.Selection.SelectIter (iter);
			}
		}
		
		public System.Windows.FrameworkElement Selection {
			get { return selection; }
		}
		
		void OnButtonRelease (object s, EventArgs a)
		{
			NotifyActivated ();
		}
		
		void NotifyActivated ()
		{
			TreeIter iter;
			if (!tree.Selection.GetSelected (out iter))
				return;
			selection = (System.Windows.FrameworkElement) store.GetValue (iter, 2);
			if (WidgetActivated != null)
				WidgetActivated (this, EventArgs.Empty);
		}
	}
}
